ulong DecompressData(uint nStartAddr){
//Chrono Trigger Decompression Routine
//Reverse engineered by Michael Springer (evilpeer@hotmail.com)
bool bCarryFlag = false;
ushort nCompressedSize = (ushort) (RomData[nStartAddr] | (RomData[nStartAddr + 1] << 8));;
uint nBytePos = nStartAddr + 2;
uint nByteAfter = nBytePos + nCompressedSize;
byte nBitCtr;
byte nCurByte;
byte nMem0D;
uint nWorkPos = 0;
bool bSmallerBitWidth = false;
if((RomData[nByteAfter] & 0xC0) != 0){
bSmallerBitWidth = true;
}
//C3/076B: A908 LDA #$08
//C3/076D: 850B STA nBitCtr
nBitCtr = 8;
while(true){
//C3/076F: E409 CPX nByteAfter
//C3/0771: F056 BEQ $07C9
if(nBytePos == nByteAfter){
//C3/07C9: BD0000 LDA $0000,X
nCurByte = RomData[nBytePos];
//C3/07CC: 293F AND #$3F
nCurByte &= 0x3F;
//C3/07CE: F012 BEQ $07E2
if(nCurByte == 0){
//C3/07E2: 4CA408 JMP $08A4
return nWorkPos;
}
//C3/07D0: 850B STA nBitCtr
nBitCtr = nCurByte;
//C3/07D2: C221 REP #$21
bCarryFlag = false;
//C3/07D4: BD0100 LDA $0001,X
//C3/07D7: 6500 ADC $00
//C3/07D9: 8509 STA nByteAfter
nByteAfter = (uint) (nStartAddr + ((RomData[nBytePos + 2] << 8) | RomData[nBytePos + 1]));
//C3/07DB: E8 INX
//C3/07DC: E8 INX
//C3/07DD: E8 INX
nBytePos += 3;
//C3/07DE: E220 SEP #$20
//C3/07E0: 808D BRA $076F
}
else{
//C3/0773: BD0000 LDA $0000,X
nCurByte = RomData[nBytePos];
//C3/0776: F0AB BEQ $0723
if(nCurByte == 0){
//C3/0723: BD0100 LDA $0001,X
nCurByte = RomData[nBytePos + 1];
//C3/0726: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/072A: BD0200 LDA $0002,X
nCurByte = RomData[nBytePos + 2];
//C3/072D: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/0731: BD0300 LDA $0003,X
nCurByte = RomData[nBytePos + 3];
//C3/0734: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/0738: BD0400 LDA $0004,X
nCurByte = RomData[nBytePos + 4];
//C3/073B: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/073F: BD0500 LDA $0005,X
nCurByte = RomData[nBytePos + 5];
//C3/0742: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/0746: BD0600 LDA $0006,X
nCurByte = RomData[nBytePos + 6];
//C3/0749: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/074D: BD0700 LDA $0007,X
nCurByte = RomData[nBytePos + 7];
//C3/0750: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/0754: BD0800 LDA $0008,X
nCurByte = RomData[nBytePos + 8];
//C3/0757: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/075B: C221 REP #$21
bCarryFlag = false;
//C3/075D: 8A TXA
//C3/075E: 690900 ADC #$0009
//C3/0761: AA TAX
nBytePos += 9;
//C3/0762: 98 TYA
//C3/0763: 690800 ADC #$0008
//C3/0766: A8 TAY
//C3/0767: E220 SEP #$20
//C3/0769: 8004 BRA $076F
}
else{
//C3/0778: E8 INX
nBytePos++;
//C3/0779: 4A LSR A
//C3/077A: 850D STA $0D
if((nCurByte & 0x01) == 1){
bCarryFlag = true;
}
else{
bCarryFlag = false;
}
nCurByte >>= 1;
nMem0D = nCurByte;
//C3/077C: B01C BCS $079A
if(bCarryFlag){
CTCopyBytes(ref nBytePos, ref nWorkPos, bSmallerBitWidth);
}
else{
//C3/077E: BD0000 LDA $0000,X
nCurByte = RomData[nBytePos];
//C3/0781: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/0785: C8 INY
//C3/0786: E8 INX
nBytePos++;
}
while(true){
//C3/0787: C60B DEC nBitCtr
nBitCtr--;
//C3/0789: F0E0 BEQ $076B
if(nBitCtr == 0){
nBitCtr = 8;
break;
}
else{
//C3/078B: 460D LSR $0D
if((nMem0D & 0x01) == 1){
bCarryFlag = true;
}
else{
bCarryFlag = false;
}
nMem0D >>= 1;
//C3/078D: B00B BCS $079A
if(bCarryFlag){
CTCopyBytes(ref nBytePos, ref nWorkPos, bSmallerBitWidth);
}
else{
//C3/078F: BD0000 LDA $0000,X
nCurByte = RomData[nBytePos];
//C3/0792: 8F802100 STA $002180
WorkingBuffer[nWorkPos++] = nCurByte;
//C3/0796: C8 INY
//C3/0797: E8 INX
nBytePos++;
//C3/0798: 80ED BRA $0787
}
}
}
}
}
}
}
void CTCopyBytes(ref uint nBytePos, ref uint nWorkPos, bool bSmallerBitWidth){
byte nBytesCopyNum;
ushort nBytesCopyOff;
//C3/079A: BD0100 LDA $0001,X
nBytesCopyNum = RomData[nBytePos + 1];
//C3/079D: 4A LSR A
//C3/079E: 4A LSR A
//C3/079F: 4A LSR A
if(bSmallerBitWidth){
nBytesCopyNum >>= 3;
}
else{
nBytesCopyNum >>= 4;
}
//C3/07A0: 1A INC A
//C3/07A1: 1A INC A
nBytesCopyNum += 2;
//C3/07A2: 850F STA $0F
//C3/07A4: C220 REP #$20
//C3/07A6: BD0000 LDA $0000,X
nBytesCopyOff = (ushort) ((RomData[nBytePos + 1] << 8) | RomData[nBytePos]);
//C3/07A9: 29FF07 AND #$07FF
//C3/07AC: 8515 STA $15
if(bSmallerBitWidth){
nBytesCopyOff &= 0x07FF;
}
else{
nBytesCopyOff &= 0x0FFF;
}
//C3/07AE: 98 TYA
//C3/07AF: 38 SEC
//C3/07B0: E515 SBC $15
//C3/07B2: 8615 STX $15
//C3/07B4: AA TAX
//C3/07B5: A50F LDA $0F
//C3/07B7: 8B PHB
//C3/07B8: 547E7E MVN $7E,$7E
for(int i = 0; i < nBytesCopyNum + 1; i++){
WorkingBuffer[nWorkPos + i] = WorkingBuffer[nWorkPos - nBytesCopyOff + i];
}
nWorkPos += (uint) (nBytesCopyNum + 1);
//C3/07BB: AB PLB
//C3/07BC: 98 TYA
//C3/07BD: 8F812100 STA $002181
//C3/07C1: E220 SEP #$20
//C3/07C3: A615 LDX $15
//C3/07C5: E8 INX
//C3/07C6: E8 INX
nBytePos += 2;
//C3/07C7: 80BE BRA $0787
}